﻿using System;
using System.IO;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;

public abstract class DFR_SettingsEditor<T> where T : ScriptableObject {

    public const string PROJECT_LABEL = "DFR";

    public static SettingsProvider CreateProvider(string label, SettingsScope scope, Action<SerializedObject> guiHandler, bool isResource = false) {
        if (isResource) {
            GetResourceFilePath();
        } else {
            GetFilePath(scope);
        }
        m_GUIHandler = guiHandler;
        var prefixProvider = scope == SettingsScope.Project ? "Project" : "Preferences";
        return new SettingsProvider($"{prefixProvider}/{PROJECT_LABEL}/{label}", scope) {
            label = label,
            guiHandler = OnGUI,
            activateHandler = OnActivate,
            deactivateHandler = OnDeactivate,
        };
    }

    private static Action<SerializedObject> m_GUIHandler;

    private static SerializedObject m_SerializedObject;
    private static T m_Settings;

    private static string m_FilePath;
    public static string GetFilePath(SettingsScope scope) {
        var prefixFilePath = scope == SettingsScope.Project ? "Project" : "User";
        m_FilePath = $"{prefixFilePath}Settings/{PROJECT_LABEL}/{typeof(T).Name}.asset";
        return m_FilePath;
    }

    public static string GetResourceFilePath() {
        m_FilePath = $"Assets/Resources/{PROJECT_LABEL}/{typeof(T).Name}.asset";
        return m_FilePath;
    }

    private static void OnActivate(string _, VisualElement __) => DoActivate();
    private static void DoActivate() {
        if (!File.Exists(m_FilePath)) {
            if (!Directory.Exists(Path.GetDirectoryName(m_FilePath))) {
                Directory.CreateDirectory(Path.GetDirectoryName(m_FilePath));
            }
            m_Settings = ScriptableObject.CreateInstance<T>();
            m_Settings.name = typeof(T).Name;
            InternalEditorUtility.SaveToSerializedFileAndForget(new[] { m_Settings }, m_FilePath, true);
            UnityEditor.AssetDatabase.Refresh();
        } else {
            var files = InternalEditorUtility.LoadSerializedFileAndForget(m_FilePath);
            m_Settings = (T)files[0];
        }
        m_SerializedObject = new SerializedObject(m_Settings);
    }

    private static void OnDeactivate() {
        if (m_SerializedObject != null) {
            m_SerializedObject.Dispose();
            m_SerializedObject = null;
        }
        m_Settings = null;
    }

    private static void OnGUI(string _) {
        if (EditorApplication.isPlayingOrWillChangePlaymode) {
            return;
        }
        if (m_Settings == null) {
            DoActivate();
        }
        m_SerializedObject.Update();
        m_GUIHandler.Invoke(m_SerializedObject);
        m_SerializedObject.ApplyModifiedPropertiesWithoutUndo();
        InternalEditorUtility.SaveToSerializedFileAndForget(new[] { m_Settings }, m_FilePath, true);
    }
}

